package es.ugr.beequizz.controller;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import es.ugr.beequizz.bean.ClasificacionBean;
import es.ugr.beequizz.bean.InformacionPartidaBean;
import es.ugr.beequizz.bean.InformacionUsuarioBean;
import es.ugr.beequizz.bean.MisPartidasBean;
import es.ugr.beequizz.bean.PartidaBean;
import es.ugr.beequizz.dto.ClasificacionDTO;
import es.ugr.beequizz.dto.IdNombreDTO;
import es.ugr.beequizz.dto.InformacionPartidaDTO;
import es.ugr.beequizz.dto.JuegoDTO;
import es.ugr.beequizz.dto.MisPartidasDTO;
import es.ugr.beequizz.dto.PartidaDTO;
import es.ugr.beequizz.dto.ResultadoDTO;
import es.ugr.beequizz.dto.UrlDTO;
import es.ugr.beequizz.model.Juego;
import es.ugr.beequizz.services.AsignaturaService;
import es.ugr.beequizz.services.DificultadService;
import es.ugr.beequizz.services.JuegoService;
import es.ugr.beequizz.services.PartidaService;
import es.ugr.beequizz.services.UsuarioService;

@Controller
@RequestMapping(value = "/plataforma")
public class PlataformaController {
	
	@Autowired
	private JuegoService juegoService;
	
	@Autowired
	private SessionRegistry sessionRegistry;
	
	@Autowired
	private UsuarioService usuarioService;
	
	@Autowired
	private PartidaService partidaService;
	
	@Autowired
	private DificultadService dificultadService;
	
	@Autowired
	private AsignaturaService asignaturaService;
	
	
	
	@RequestMapping(value="/incluirJuego", method= RequestMethod.POST,
	produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
	@ResponseBody
	public ResultadoDTO incluirJuego(@RequestBody JuegoDTO juegoDTO) {
		
		final Juego juego = new Juego();
		juego.setNombre(juegoDTO.getNombre());
		juego.setUrl(juegoDTO.getUrl());
		
		juegoService.incluirJuego(juego);
		
		return new ResultadoDTO("SUCCESS");
		
	}
	

	@RequestMapping(value = "/agregarJuegos", method = RequestMethod.GET)
	@ResponseBody
	public List<IdNombreDTO> agregarJuegos() {
		
		final List<Juego> juegos = juegoService.agregarJuegos();
		
		final List<IdNombreDTO> listaJuegos =  new ArrayList<IdNombreDTO>();
		
		for (Juego juego : juegos){
			
			final IdNombreDTO dto = new IdNombreDTO();
			dto.setId(juego.getId());
			dto.setNombre(juego.getNombre());
			listaJuegos.add(dto);
		}
		
		return listaJuegos;
		
	}
	
	/*Metodo para recuperar la url del juego deseado*/
	
	@RequestMapping(value= "/urlJuego", method= RequestMethod.GET, 
			produces = MediaType.APPLICATION_JSON_VALUE, params= {"id"})
	@ResponseBody
	public UrlDTO cargarJuego(@RequestParam(value = "id") Long id){
				
		final String url = juegoService.cargarJuego(id);
		final UrlDTO urlJuego = new UrlDTO();
		
		urlJuego.setUrl(url);
		
		return urlJuego;
		
	}
	
	/*Metdo para recuperar los usuarios conectados a la plataforma*/
	
	@RequestMapping(value = "/usuariosConectados", method = RequestMethod.GET)
	@ResponseBody
	public List<IdNombreDTO> recuperarUsuariosConectados() {
		
		final List<Object> usuariosConectados = sessionRegistry.getAllPrincipals();
		
		final List<IdNombreDTO> listaUsuariosConectados =  new ArrayList<IdNombreDTO>();
		
		for (Object usuario : usuariosConectados){
			User user = (User) usuario;
			final String username = user.getUsername();
			
			final IdNombreDTO dto = new IdNombreDTO();
			final Long id = usuarioService.recuperarIdUsuario(username);
			
			dto.setId(id);
			dto.setNombre(username);
			
			listaUsuariosConectados.add(dto);
			
		}
		
		return listaUsuariosConectados;
	}
	
	/*Usuarios : Metodo para recuperar todos los usuarios de la lista*/
	@RequestMapping(value = "/usuarios", method = RequestMethod.GET,
			produces = MediaType.APPLICATION_JSON_VALUE, params= {"idUsuario"})
	@ResponseBody
	public List<IdNombreDTO> recuperarUsuarios(@RequestParam(value = "idUsuario") Long idUsuario){
				
		final List<InformacionUsuarioBean> usuarioBean = usuarioService.recuperarUsuarios(idUsuario);
		
		final List<IdNombreDTO> listaUsuarios =  new ArrayList<IdNombreDTO>();
		
		for (InformacionUsuarioBean usuario : usuarioBean){
			final IdNombreDTO dto = new IdNombreDTO();
			
			final String username = usuario.getApodo();
			final Long id = usuario.getId();
			
			dto.setId(id);
			dto.setNombre(username);
			
			listaUsuarios.add(dto);
			
		}
		return listaUsuarios;
		
	}
	
	/*Metodo para recuperar las partidas que un usuario tiene en curso*/
	
	@RequestMapping(value = "/partidasUsuario", method = RequestMethod.GET,
			produces = MediaType.APPLICATION_JSON_VALUE, params= {"idUsuario"})
	@ResponseBody
	public List<PartidaDTO> recuperarPartidas(@RequestParam(value = "idUsuario") Long idUsuario){
		
		final List<PartidaBean> partidasBean = partidaService.recuperarPartidas(idUsuario);
		final List<PartidaDTO> listaPartidas =  new ArrayList<PartidaDTO>();
		
		for (PartidaBean partida : partidasBean) {
			
			final PartidaDTO dto = new PartidaDTO();
			
			Long idPartida = partida.getId();
			Long idJuego = partida.getJuego_id();
			
			dto.setId(idPartida);
			dto.setJuegoId(idJuego);
			
			listaPartidas.add(dto);			
		}
		
		return listaPartidas;
		
	}
	/*Recuperar informaciones de los partidos en curso*/
	@RequestMapping(value = "/partidasEnCurso", method = RequestMethod.GET,
			produces = MediaType.APPLICATION_JSON_VALUE, params= {"idUsuario", "idJuego"})
	@ResponseBody
	public List<InformacionPartidaDTO> recuperarPartidasEnCurso(@RequestParam(value = "idUsuario") Long idUsuario, @RequestParam(value = "idJuego") Long idJuego){
		
		final List<InformacionPartidaBean> informacionPartidasBean = partidaService.recuperarPartidasEnCurso(idUsuario, idJuego);
		
		
		final List<InformacionPartidaDTO> listaPartidas =  new ArrayList<InformacionPartidaDTO>();
		
		for (InformacionPartidaBean partida : informacionPartidasBean) {
			
			final InformacionPartidaDTO dto = new InformacionPartidaDTO();
			
			final Long idPartida = partida.getPartidaId();
			final String apodo = partida.getApodo();
			final Date fecha = partida.getFecha();
			final Long idDificultad = partida.getDificultadId();
			final Long idTema = partida.getTemaId();
			
			
			dto.setParticipantes(this.recuperarParticipantes(idPartida));
			
			dto.setPartidaId(idPartida);
			dto.setApodo(apodo);
			dto.setFecha(this.formatearFecha(fecha));
			
			if (idDificultad != null) {
				dto.setIdDificultad(idDificultad);
				dto.setLabelDificultad(dificultadService.getNombre(idDificultad));
			}
			
			if (idTema != null) {
				dto.setIdTema(idTema);
				dto.setLabelTema(asignaturaService.getNombre(idTema));
			}
			
			listaPartidas.add(dto);			
		}
		
		return listaPartidas;
	}
	
	/*Recuperar informacion de la partida*/
	@RequestMapping(value = "/informacionPartida", method = RequestMethod.GET,
			produces = MediaType.APPLICATION_JSON_VALUE, params= {"partidaId"})
	@ResponseBody
	public InformacionPartidaDTO recuperarInformacionPartida(@RequestParam(value = "partidaId") Long idPartida) {
		
		final InformacionPartidaBean partida = partidaService.recuperarInformacionPartida(idPartida);
		
		final InformacionPartidaDTO dto = new InformacionPartidaDTO();

		final String apodo = partida.getApodo();
		final Date fecha = partida.getFecha();
		final Long idDificultad = partida.getDificultadId();
		final Long idTema = partida.getTemaId();
			
		dto.setPartidaId(idPartida);
		dto.setApodo(apodo);
		dto.setFecha(this.formatearFecha(fecha));
			
		if (idDificultad != null) {
			dto.setIdDificultad(idDificultad);
			dto.setLabelDificultad(dificultadService.getNombre(idDificultad));
		}

		if (idTema != null) {
			dto.setIdTema(idTema);
			dto.setLabelTema(asignaturaService.getNombre(idTema));
		}

		
		return dto;
	}
	
	@RequestMapping(value = "/resultadosMisPartidas", method = RequestMethod.GET,
			produces = MediaType.APPLICATION_JSON_VALUE)
	@ResponseBody
	public List<MisPartidasDTO> recuperarResultadosMisPartidas() {


		final String username = SecurityContextHolder.getContext().getAuthentication().getName();
		
		Long jugadorId = usuarioService.recuperarIdUsuario(username);
		
		
		final List<MisPartidasBean> partidas = partidaService.recuperarResultadosMisPartidas(jugadorId);
		final List<MisPartidasDTO> dtos = new ArrayList<MisPartidasDTO>();
		
		for (MisPartidasBean partida : partidas) {
			MisPartidasDTO dto = new MisPartidasDTO();
			
			dto.setAsignatura(partida.getAsignatura());
			dto.setDificultad(partida.getDificultad());
			dto.setFecha(this.formatearFecha(partida.getFecha()));
			dto.setNombreJuego(partida.getNombreJuego());
			dto.setPuntuacion(partida.getPuntuacion());
			dto.setParticipantes(recuperarParticipantes(partida.getIdPartida()));
			
			dtos.add(dto);
		}
		return dtos;
	}
	
	@RequestMapping(value = "/clasificacion", method = RequestMethod.GET,
			produces = MediaType.APPLICATION_JSON_VALUE, params= {"juegoId","asignaturaId","dificultadId"})
	@ResponseBody
	public List<ClasificacionDTO> recuperarClasificacion(@RequestParam(value = "juegoId") Long juegoId, @RequestParam(value = "asignaturaId") Long asignaturaId,
			@RequestParam(value = "dificultadId") Long dificultadId) {
		
		
		final List<ClasificacionBean> clasificaciones = partidaService.recuperarClasificacion(juegoId, asignaturaId, dificultadId);
		final List<ClasificacionDTO> dtos = new ArrayList<ClasificacionDTO>();
		
		for (ClasificacionBean clasificacion : clasificaciones) {
			ClasificacionDTO dto = new ClasificacionDTO();
			dto.setNombre(clasificacion.getNombre());
			dto.setPartidasGanadas(clasificacion.getPartidasGanadas());
			dtos.add(dto);
		}
		return dtos;
	}
	
	private String formatearFecha(final Date fecha) {
		final SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
		return sdf.format(fecha);
	}
	
	private String recuperarParticipantes(final Long idPartida) {
		final List<String> participantes = partidaService.recuperarListaParticipantes(idPartida);
		StringBuilder sb = new StringBuilder();
		for (String participante : participantes) {
			sb.append(participante);
			sb.append(" ");
		}
		return sb.toString();
	}
}
